package com.atmilan.quartz.sync.push.service.impl;

import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.atmilan.quartz.constant.enums.SuppliersIdEnum;
import com.atmilan.quartz.model.entity.BuyerProductDO;
import com.atmilan.quartz.model.entity.buyer.BuyerProduct;
import com.atmilan.quartz.model.entity.buyer.BuyerProductSkuMerged;
import com.atmilan.quartz.sync.pull.buyer.service.IBuyerProductService;
import com.atmilan.quartz.sync.pull.buyer.service.IBuyerProductSkuMergedService;
import com.atmilan.quartz.sync.push.service.IProductListenerService;
import com.atmilan.quartz.sync.push.service.ProductPushService;
import com.atmilan.quartz.utils.PriceUtil;
import com.atmilan.quartz.utils.RedisUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import lombok.extern.slf4j.Slf4j;

/**
 * x
 *
 * @author muyu.myw
 * @date 2020/9/24 11:01
 */
@Slf4j
@Service
public class ProductPushServiceImpl implements ProductPushService {
    ExecutorService service = Executors.newFixedThreadPool(18);
    int countPushed = 0;
    int countStart = 0;
    Lock lock = new ReentrantLock();
    @Autowired
    PriceUtil priceUtil;
    @Autowired
    RedisUtil redisUtil;
    @Autowired
    IBuyerProductService buyerProductService;
    @Autowired
    IBuyerProductSkuMergedService buyerProductSkuMergedService;
    @Autowired
    IProductListenerService productListenerService;

    @Override
    public Boolean pushBuyerProduct() {
        long start = System.currentTimeMillis();
        countStart = 0;
        int pageNo = 1;
        int pageSize = 300;
        // 条件
        LambdaQueryWrapper<BuyerProduct> lambdaQueryWrapper = Wrappers.<BuyerProduct>lambdaQuery().gt(BuyerProduct::getSalePrice, 0);

        int count = buyerProductService.count(lambdaQueryWrapper);
        int maxPage = count == 0 ? 0 : (count / pageSize) + 1;
        log.info("--------------- 开始分页查询buyer商品源数据, 本次更新总条数为: {} ---------------", count);

        while (pageNo <= maxPage) {
            // 分页查询源数据
            PageHelper.startPage(pageNo, pageSize);
            List<BuyerProduct> buyerProducts = buyerProductService.list(lambdaQueryWrapper);
            PageInfo<BuyerProduct> pageInfo = PageInfo.of(buyerProducts);

            int tempPageNo = pageNo;
            service.execute(() -> {
                try {
                    long elapsedTime = ((System.currentTimeMillis() - start) / tempPageNo) / 1000;
                    log.warn("--------------- 第: {} 页, --------------- 总页数: {} 平均每页耗时: {} 秒 , 预估剩余: {}分钟---------------", tempPageNo, maxPage, elapsedTime, ((maxPage - tempPageNo) * elapsedTime)/60);
                    pageInfo.getList().forEach(product -> {
                        countStart++;
                        processOne(product);
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });

            pageNo++;
        }
        log.warn("--------------- 推送买手库商品结束,  总推送条数: {},  耗时: {} 秒---------------", count, ((System.currentTimeMillis() - start) / 1000));
        return true;
    }

    @Override
    public Boolean pushAllBuyerProduct() {
        if (lock.tryLock()) {
            try {
                pushBuyerProduct();
            } finally {
                lock.unlock();
            }
        } else {
            log.error("已经有线程在同步商品, 不要重复执行!");
        }
        return true;
    }

    @Override
    public Boolean pushBuyerProduct(List<String> goodsIds) {
        List<BuyerProduct> list = buyerProductService.list(Wrappers.<BuyerProduct>lambdaQuery().in(BuyerProduct::getGoodsId, goodsIds));
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(product -> processOne(product));
        }
        return true;
    }

    private void processOne(BuyerProduct product) {
        BuyerProductDO buyerProductDO = new BuyerProductDO();
        BeanUtils.copyProperties(product, buyerProductDO);

        // 这里从 sku_merged 表里取，已经去重并且合并了库存
        List<BuyerProductSkuMerged> list = buyerProductSkuMergedService.list(Wrappers.<BuyerProductSkuMerged>lambdaQuery().eq(BuyerProductSkuMerged::getGoodsId, product.getGoodsId()).gt(BuyerProductSkuMerged::getStock, 0)
        //                .eq(BuyerProductSkuMerged::getQihuo, 0)
        //                .ne(BuyerProductSkuMerged::getSize, "")
        //                .isNotNull(BuyerProductSkuMerged::getSize)
        );
        buyerProductDO.setSkuList(list);

        try {

            // 分发前：小黑仓和买手端价格数据换算调整处理(数据计算转换)
            priceAdjustCrmeb(buyerProductDO);
            productListenerService.receiveProductMsg(buyerProductDO);
        } catch (Exception ex) {
            log.error("processOne exception! e: ", ex);
        }
    }

    /**
     * 买手库价格调整
     * @Description:  
     * @author daigb 
     * @param @param product
     * @param @return
     * @return BuyerProductDO
     * @throws
     */
    private BuyerProductDO priceAdjustCrmeb(BuyerProductDO product) {
        String promotePriceStr = product.getPromotePrice();
        // 活动价
        BigDecimal promotePrice = StringUtils.isNotEmpty(promotePriceStr) ? new BigDecimal(promotePriceStr) : BigDecimal.ZERO;
        product.setPromotePrice(promotePrice.toString());
        // 销售价
        BigDecimal salePrice = StringUtils.isNotEmpty(product.getSalePrice()) ? new BigDecimal(product.getSalePrice()) : BigDecimal.ZERO;
        // 成本价
        String erpPromPriceStr = product.getErpPromPrice();
        BigDecimal erpPromPrice = StringUtils.isNotEmpty(erpPromPriceStr) ? new BigDecimal(erpPromPriceStr) : BigDecimal.ZERO;
        String erpPriceStr = product.getErpPrice();
        product.setErpPromPrice(erpPromPrice.toString());

        // 有活动价格(满足活动价大于0且活动价小于销售价)
//        if (StringUtils.isNotEmpty(promotePriceStr) && salePrice.compareTo(promotePrice) == 1 && new BigDecimal(0).compareTo(promotePrice) == -1) {
//            product.setSalePrice(promotePriceStr);
//            product.setPromoteFlag(true);
//            product.setSourceCost(erpPromPriceStr);
//            product.setErpPrice(erpPromPrice.toString());
//            product.setErpPromFlag(true);
//        } else {
        product.setSalePrice(salePrice.toString());
        product.setPromoteFlag(false);
        product.setSourceCost(erpPriceStr);
        product.setErpPrice(erpPromPriceStr);
        product.setErpPromFlag(false);
//        }

        // 供应商名称处理
        Integer suppliersId = product.getSuppliersId();
        product.setSuppliersName(SuppliersIdEnum.getEnumValue(suppliersId+""));

        return product;
    }

}
